﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Net;
using twlib;
using System.IO;

//B10C1148

namespace TeamWork_Client
{
    public partial class Form1 : Form
    {
        private RCon remote_console;
        public static string server;
        ChatClient cc;
        //string nickname;

        public static UserDetails Loggedin = new UserDetails() { Username = "user_" + new Random().Next().ToString("X") };

        string translate_lang(string lang)
        {
            switch(lang)
            {
                case "C#":
                    return Path.Combine(Environment.CurrentDirectory, @"\environment\code\CSharp-Mode.xshd");
                case "VB .NET":
                    return Path.Combine(Environment.CurrentDirectory, @"\environment\code\VBNET-Mode.xshd");
                case "C++":
                    return Path.Combine(Environment.CurrentDirectory, @"\environment\code\CPP-Mode.xshd");
                default:
                    return "";
            }
        }

        void UpdatePriviledges()
        {
            // ADM
            // CODER
            // DESIGNER
            // 
            switch (Loggedin.Role)
            {
                case "ADM":
                    Loggedin.Priviledges.AddRange(new UserPriviledges[] { UserPriviledges.DesignerUpload, UserPriviledges.DesignerDownload, UserPriviledges.CanUpload, UserPriviledges.CanModify, UserPriviledges.CanDownload, UserPriviledges.CanAccessRCon });
                    break;
                case "CODER":
                    Loggedin.Priviledges.AddRange(new UserPriviledges[] { UserPriviledges.CanDownload, UserPriviledges.CanModify });
                    break;
                case "DESIGNER":
                    Loggedin.Priviledges.AddRange(new UserPriviledges[] { UserPriviledges.DesignerDownload, UserPriviledges.DesignerUpload });
                    break;
            }
        }

        public Form1(RCon rcon)
        {
            InitializeComponent();
            remote_console = rcon;
            server = rcon.ssa;
            string lang = rcon.SendCmd("/lang?", true);
            textEditorControl1.Document.HighlightingStrategy = DigitalRune.Windows.TextEditor.Highlighting.HighlightingManager.Manager.FindHighlighter(lang);
        }

        public Form1(string s)
        {
            InitializeComponent();
            server = s;
            //nickname = File.ReadAllLines("nickname.txt")[0];
        }

        private void contextMenuStrip1_Opening(object sender, CancelEventArgs e)
        {
            /*if (remote_console.coder_accepted)
            {
                submitAnUpdateToolStripMenuItem.Enabled = false;
                submitAnUpdateToolStripMenuItem.Text = "Submit An Update...(Coder Only)";
            }*/
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Dictionary<string, string> d = new Dictionary<string, string>();
            d.Add("TYPE", "GetFiles");
            string[] files = HTTPManager.SendMessage((server + ":55987"), null, d).Split(';');
            foreach (var f in files)
            {
                if (f.Trim().Length > 0 && f != null) //Some checks.
                {
                    treeView1.Nodes.Add(f);
                }
            }
            timer1.Start();
            cc = new ChatClient(server, Loggedin.Username);
            timer2.Start();
            new System.Threading.Thread(cc_check).Start();
            //timer3.Start();
        }

        private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
        {
            if (e.Node.Text.Length > 0) //Make sure we don't send a NULL name.
            {
                string data = HTTPManager.SendMessage((server + ":55987"), "/download " + e.Node.Text, null);
                textEditorControl1.Text = data;
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            richTextBox1.SelectionStart = richTextBox1.Text.Length;
            //richTextBox1.SelectionLength = 0;
            richTextBox1.ScrollToCaret();
        }

        private void textBox2_KeyDown(object sender, KeyEventArgs e)
        {
            if (Loggedin != null)
            {
                if (textBox2.Text.Length > 0)
                {
                    if (e.KeyCode == Keys.Enter)
                    {
                        cc.SendMessage(Loggedin.Username + ": " + textBox2.Text);
                        textBox2.Text = "";
                    }
                }
            }
            else
                textBox2.Text = "Please Login First!";
        }

        StringBuilder str = new StringBuilder();

        private void timer2_Tick(object sender, EventArgs e)
        {
            richTextBox1.Text = str.ToString();
        }

        private void cc_check()
        {
            while (true)
            {
                try
                {
                    string msg = cc.reader.ReadLine();
                    str.AppendLine(msg);
                }catch(Exception ex)
                {
                    if (ex is IOException)
                    {
                        MessageBox.Show("Virtual stream to the server has been broken! Please make sure that the server is still available or that your network connection is up.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        break;
                    }
                }
            }
        }

        [DllImport("Kernel32")]
        private static extern void ExitProcess(int uExitCode);

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            Application.Exit();
            ExitProcess(0);
        }

        private void viewModificationEntriesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if(Loggedin != null)
            {
                Dictionary<string, string> Headers = new Dictionary<string, string>();
                Headers.Add("TYPE", "CodeReview");
                Headers.Add("file_name", treeView1.SelectedNode.Text);

                var t = HTTPManager.SendMessage2((server + ":55987"), null, Headers);
                BinaryReader reader = new BinaryReader(t.GetResponseStream());

                int len = reader.ReadInt32();
                List<CodeUpdateTemplate> mods = new List<CodeUpdateTemplate>();
                for (int i = 0; i < len; i++)
                {
                    CodeUpdateTemplate temp = new CodeUpdateTemplate();
                    temp.Author = reader.ReadString();
                    temp.Date = reader.ReadInt64();
                    temp.File = reader.ReadString();
                    temp.Code = reader.ReadString();
                    mods.Add(temp);
                }
                new ModDB(Headers["file_name"], mods).Show();
            }else
                MessageBox.Show("Please login first!", "Code Update", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }

        private void submitAnUpdateToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if(Loggedin != null)
            {
                Dictionary<string, string> headers = new Dictionary<string, string>();
                headers.Add("TYPE", "CodeSubmit");

                MemoryStream memsr = new MemoryStream();
                BinaryWriter writer = new BinaryWriter(memsr);
                writer.Write(Loggedin.Username);
                writer.Write(DateTime.Now.ToBinary());
                writer.Write(treeView1.SelectedNode.Text);
                writer.Write(textEditorControl1.Text);
                writer.Flush();

                var r = HTTPManager.SendMessage3((server + ":55987"), memsr.ToArray(), headers);
                if (r != null)
                    MessageBox.Show("Code Update Has Been Submitted.", "Code Update", MessageBoxButtons.OK, MessageBoxIcon.Information);
                else
                    MessageBox.Show("Something wrong happened while sending buffered data for code update. Return value was: null.", "Code Update", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }else
                MessageBox.Show("Please login first!", "Code Update", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
            ExitProcess(0);
        }

        private void registerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Register reg = new Register();
            reg.ShowDialog();
            Loggedin = reg.User;
            if(Loggedin != null)
                UpdatePriviledges();
        }

        private void loginToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Login lg = new Login();
            lg.ShowDialog();
            Loggedin = lg.User;
            if (Loggedin != null)
                UpdatePriviledges();
        }

        private void timer3_Tick(object sender, EventArgs e)
        {
            if(Loggedin != null)
            {
                Dictionary<string, string> headers = new Dictionary<string, string>();
                headers.Add("TYPE", "HeartBeat");
                headers.Add("UID", Loggedin.ID.ToString());
                HTTPManager.SendMessage2(Form1.server + ":55987", "", headers);
            }
        }

        private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (tabControl1.SelectedTab.Text.ToLower() == "browse code")
            {
                if (Loggedin == null)
                {
                    MessageBox.Show("You are not loggedin. Please login first or register if you are not a member of this project.", "Credentials Are Invalid", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    tabControl1.SelectedIndex = 0;
                }
            }
        }

    }
}
